﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;

namespace CommonLibrary.BcSecurity
{
    public static class BcSecurity
    {
        #region RsaKey To BcKey

        public static void GetBcKey(string in_RsaPrivateKey, out string out_BcPrivateKey, out string out_BcPublicKey)
        {
            RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(2048);
            rsaProvider.FromXmlString(in_RsaPrivateKey);
            AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetRsaKeyPair(rsaProvider);

            AsymmetricKeyParameter privateKey = keyPair.Private;
            AsymmetricKeyParameter publicKey = keyPair.Public;

            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
            byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetDerEncoded();
            out_BcPrivateKey = Convert.ToBase64String(serializedPrivateBytes);


            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
            byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            out_BcPublicKey = Convert.ToBase64String(serializedPublicBytes);
        }

        public static string GetBcPrivateKey(string in_RsaPrivateKey)
        {
            string out_BcPrivateKey = "";
            string out_BcPublicKey = "";

            GetBcKey(in_RsaPrivateKey, out out_BcPrivateKey, out out_BcPublicKey);
            return out_BcPrivateKey;
        }

        public static string GetBcPublicKey(string in_RsaPublicKey)
        {
            RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(2048);
            rsaProvider.FromXmlString(in_RsaPublicKey);

            RsaKeyParameters rsaPublicKey = DotNetUtilities.GetRsaPublicKey(rsaProvider);

            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rsaPublicKey);
            byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            string out_BcPublicKey = Convert.ToBase64String(serializedPublicBytes);

            return out_BcPublicKey;
        }

        #endregion



        #region BcKey To RsaKey

        public static void GetRsaKey(string in_BcPrivateKey, out string out_RsaPrivateKey, out string out_RsaPublicKey)
        {
            byte[] privateBytes = Convert.FromBase64String(in_BcPrivateKey);
            AsymmetricKeyParameter privateKey = PrivateKeyFactory.CreateKey(privateBytes);

            RSA rsa = DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)privateKey);
            out_RsaPrivateKey = rsa.ToXmlString(true);
            out_RsaPublicKey = rsa.ToXmlString(false);
        }

        public static string GetRsaPrivateKey(string in_BcPrivateKey)
        {
            string out_RsaPrivateKey = "";
            string out_RsaPublicKey = "";

            GetRsaKey(in_BcPrivateKey, out out_RsaPrivateKey, out out_RsaPublicKey);

            return out_RsaPrivateKey;
        }

        public static string GetRsaPublicKey(string in_BcPublicKey)
        {
            byte[] publicBytes = Convert.FromBase64String(in_BcPublicKey);
            AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(publicBytes);

            RSA rsa = DotNetUtilities.ToRSA((RsaKeyParameters)publicKey);
            string xmlPublicKey = rsa.ToXmlString(false);
            return xmlPublicKey;
        }

        #endregion



        #region Rsa 私钥加密，公钥解密

        public static string EncryptStringByRsaPrivate(string in_str, string in_RsaPrivateKey)
        {
            string bcPrivateKey = GetBcPrivateKey(in_RsaPrivateKey);

            return EncryptStringByBcPrivate(in_str, bcPrivateKey);
        }

        public static string DecryptStringByRsaPublic(string in_str, string in_RsaPublicKey)
        {
            string bcPublicKey = GetBcPublicKey(in_RsaPublicKey);

            return DecryptStringByBcPublic(in_str, bcPublicKey);
        }

        #endregion



        #region Rsa 私钥加密，公钥解密

        public static string EncryptStringByBcPrivate(string in_str, string in_BcPrivateKey)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(in_str);

            byte[] privateBytes = Convert.FromBase64String(in_BcPrivateKey);
            AsymmetricKeyParameter privateKey = PrivateKeyFactory.CreateKey(privateBytes);

            IAsymmetricBlockCipher engine = new RsaEngine();
            engine.Init(true, privateKey);

            bytes = engine.ProcessBlock(bytes, 0, bytes.Length);
            return Convert.ToBase64String(bytes);
        }

        public static string DecryptStringByBcPublic(string in_str, string in_BcPublicKey)
        {
            byte[] bytes = Convert.FromBase64String(in_str);

            byte[] publicBytes = Convert.FromBase64String(in_BcPublicKey);
            AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(publicBytes);

            IAsymmetricBlockCipher engine = new RsaEngine();
            engine.Init(false, publicKey);

            bytes = engine.ProcessBlock(bytes, 0, bytes.Length);
            return Encoding.UTF8.GetString(bytes);
        }

        #endregion
    }
}
